using System;
using System.Collections.Generic;
using System.Text;
using com.db4o;
using Microsoft.ApplicationBlocks.ExceptionManagement;
using System.IO;
namespace StockDownloader.Persistance
{
    public class DataPersitance : IDisposable
    {
        public const string _yapFileName = "stocks.yap";
        private ObjectContainer _db;
        

        /// <summary>
        /// Calling this method opens a Db40 container to be used for querying and locks the file.
        /// 
        /// NOTE: The caller is responsible for calling Dispose() which closes the database properly.  
        /// Failure to do so leaves the object database open and keeps the databse file locked.
        /// </summary>
        /// <param name="yapFileName"></param>
        public void OpenDatabase(string yapFileName, string stockName)
        {
            com.db4o.config.Configuration c = Db4o.configure();
            c.activationDepth(1);
            if (yapFileName != null)
            {
                if (stockName != null)
                {
                    yapFileName = Path.GetDirectoryName(yapFileName) + "stockName-" + Path.GetFileName(yapFileName);
                }

                _db = Db4o.openFile(yapFileName);
            }
            else
            {
                if (stockName != null)
                {
                    _db = Db4o.openFile(Path.GetDirectoryName(_yapFileName) + "stockName-" + Path.GetFileName(_yapFileName));
                }
                else
                {
                    _db = Db4o.openFile(_yapFileName);
                }
            }
        }

        public void CloseDatabase()
        {
            if (_db != null)
                _db.close();
        }

        public Stocks.StockLog[] GetStoredStockList()
        {
            Stocks.StockLog[] slog = null;
            com.db4o.query.Query q = _db.query();
            q.constrain(typeof(Stocks.StockLog));
            ObjectSet os = q.execute();
            if (os.Count > 0)
            {
                slog = new Stocks.StockLog[os.Count];
                os.CopyTo(slog,0);

            }
            return slog;
        }
        public static DateTime GetLatestStockDate(string stockName)
        {
            return DateTime.Now;
        }
        public static Stocks.StockInstanceDataCollectionEx GetStockLogStatic(string stockName, DateTime startDate, DateTime endDate)
        {
            DataPersitance dp = new DataPersitance();
            Stocks.StockInstanceDataCollectionEx result = null;
            dp.OpenDatabase(DataPersitance._yapFileName, stockName);
            try
            {
                result = dp.GetStockLog(stockName, startDate, endDate);
            }
            finally
            {
                dp.CloseDatabase();
            }
            return result;
        }

        public Stocks.StockInstanceDataCollectionEx GetStockLog(string stockName, DateTime startDate, DateTime endDate)
        {
            Stocks.StockInstanceDataCollectionEx collection = new Stocks.StockInstanceDataCollectionEx();
            com.db4o.query.Query q = _db.query();
            q.constrain(typeof(Stocks.StockInstantData));
            //q.descend("_symbol").constrain(stockName);
            q.constrain(new DateInclusionEvaluator(startDate,endDate, stockName));
            ObjectSet os = q.execute();
            if (os.Count > 0)
            {
                collection.AddRange(os);
            }
            return collection;
        }

        public static void SaveStockLog(Stocks.StockLog log, string yapFileName)
        {
            
            DataPersitance dp = new DataPersitance();
            dp.OpenDatabase(yapFileName, log.Symbol);
            
            
            try
            {
                com.db4o.query.Query q = dp._db.query();
                q.constrain(typeof(Stocks.StockLog));
                q.descend("_symbol").constrain(log.Symbol);
                ObjectSet os = q.execute();
                if (os.Count > 0)
                {
                    for(int i = 0; i < os.Count; i++)
                    {
                        dp._db.delete(os[i]);
                    }
                    dp._db.set(log);

                }
                else
                {
                    dp._db.set(log);
                    dp._db.commit();
                    
                }
            }
            catch (Exception err)
            {
                ExceptionManager.Publish(err);
            }
            finally
            {

                if (dp._db != null)
                    dp._db.close();
            }
        }
        public static void SaveStockInstanceDataCollection(Stocks.StockInstanceDataCollectionEx collection, string yapFileName)
        {
            ObjectContainer oc;
            if (yapFileName != null)
                oc = Db4o.openFile(yapFileName);
            else
                oc = Db4o.openFile(_yapFileName);
            try
            {
                com.db4o.query.Query q = oc.query();
                q.constrain(typeof(Stocks.StockInstanceDataCollectionEx));
                q.descend("_symbol").constrain(collection.Symbol);
                ObjectSet os = q.execute();
                if (os.Count > 0)
                {
                    ((Stocks.StockInstanceDataCollectionEx)os[0]).AddRange(collection);

                }
                else
                {
                    oc.set(collection);
                }
            }
            catch (Exception err)
            {
                ExceptionManager.Publish(err);
            }
            finally
            {

                if (oc != null)
                    oc.close();
            }

        }
        public static void IndexAll()
        {   

            Db4o.configure().objectClass(typeof(Stocks.StockInstanceDataCollectionEx) ).objectField("_symbol").indexed(true);
            Db4o.configure().objectClass(typeof(Stocks.StockInstantData)).objectField("__Symbol").indexed(true);
            Db4o.configure().objectClass(typeof(Stocks.StockInstantData)).objectField("__DateTime").indexed(true);
            ObjectContainer oc;
            oc = Db4o.openFile(_yapFileName);
            oc.commit();
            oc.close();

        }
        #region IDisposable Members

        public void Dispose()
        {
            if (this._db != null)
            {
                this._db.close();
            }
        }

        #endregion
    }
}
